package cz.none.bezbarier.web.controller;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import cz.none.bezbarier.web.form.RefererForm;
import cz.none.bezbarier.web.util.Constants;
import cz.none.bezbarier.web.vo.FlashMessage;
import cz.none.bezbarier.web.vo.FlashMessage.Severity;

public abstract class AController {

	private static final String FLASH_MESSAGES = "flashMessages";

	@Autowired
	private MessageSource messageSource;

	protected String redirectToReferer(RefererForm form) {
		if (null == form) {
			return "redirect:" + Constants.Page.HOME;
		}

		return redirectToPage(form.getReferer());
	}

	protected String redirectToPage(String referer) {
		if (null != referer && !referer.isEmpty()) {
			return "redirect:" + referer;
		} else {
			return "redirect:" + Constants.Page.HOME;
		}
	}

	protected void setActiveMenu(Model model, String menu) {
		model.addAttribute("menu", menu);
	}

	protected <T extends Model> void addFlashMessage(T storage, Severity severity, String messageCode,
			Object... args) {

		FlashMessage flashMessage = createMessages(severity, messageCode, args);

		addFlashMessage(storage, Collections.singletonList(flashMessage));
	}

	protected <T extends Model> void addFlashMessage(T storage, BindingResult result, Locale locale) {

		List<ObjectError> errors = result.getAllErrors();
		List<FlashMessage> flashMessages = new ArrayList<FlashMessage>();

		for (ObjectError objectError : errors) {
			flashMessages.add(createMessages(Severity.ERROR, objectError.getCode(), new Object[] {}));
		}

		addFlashMessage(storage, flashMessages);

	}

	private <T extends Model> void addFlashMessage(T redirectAttributes, List<FlashMessage> messages) {
		Map<String, Object> map = null;
		if (redirectAttributes instanceof RedirectAttributes) {
			RedirectAttributes attributes = (RedirectAttributes) redirectAttributes;
			map = (Map<String, Object>) attributes.getFlashAttributes();
		} else {
			map = redirectAttributes.asMap();
		}

		List<FlashMessage> flashMessages = (List<FlashMessage>) (map.containsKey(FLASH_MESSAGES) ? map
				.get(FLASH_MESSAGES) : new ArrayList<FlashMessage>());

		flashMessages.addAll(messages);

		map.put(FLASH_MESSAGES, flashMessages);
	}

	private FlashMessage createMessages(Severity severity, String messageCode, Object... args) {
		Locale locale = LocaleContextHolder.getLocale();

		return new FlashMessage(severity, messageSource.getMessage(messageCode, args, locale));

	}
}
